import {
  BaseRepository,
  indexPaginateBuilder,
  showBuilderEntity,
} from '@libs/common/repository';
import { Inject, Injectable } from '@nestjs/common';
import { Cron } from '@nestjs/schedule';
import { plainToInstance } from 'class-transformer';
import { In, Repository } from 'typeorm';

import { DepartmentService } from '@/dingding/department/department.service';
import { MemberService } from '@/dingding/member/member.service';

import { ProviderKey } from './department-config.providers';
import {
  FindDepartmentConfigDto,
  IndexDepartmentConfigDto,
  ShowDepartmentConfigDto,
  SwitchDepartmentConfigDto,
  UpdateDepartmentConfigDto,
} from './dto/department-config.dto';
import { DepartmentConfig } from './entities/department-config.entity';

@Injectable()
export class DepartmentConfigService extends BaseRepository {
  @Inject(ProviderKey)
  private repository: Repository<DepartmentConfig>;

  @Inject(MemberService)
  private memberService: MemberService;

  @Inject(DepartmentService)
  private departmentService: DepartmentService;

  async index(dto: IndexDepartmentConfigDto) {
    const res = await indexPaginateBuilder({
      dto,
      repository: this.repository,
    });
    return res;
  }

  show<D extends ShowDepartmentConfigDto = ShowDepartmentConfigDto>(dto: D) {
    return showBuilderEntity(this.repository, dto);
  }

  /** 返回所有符合条件的数据 */
  find(dto?: FindDepartmentConfigDto) {
    return this.repository.find({ where: dto || {} });
  }

  /** 通过 uid 查询首个部门配置 */
  async userIdFindFirstConfig(userId: string) {
    if (!userId) {
      throw new Error('用户id不能为空');
    }

    const member = await this.memberService.findOne({ userId: userId });

    if (!member) {
      throw new Error('用户不存在');
    }

    const deptId = member.deptIdList.split(',').at(-1) || member.deptIdList;

    return this.repository.findOneBy({ id: deptId });
  }

  /** 通过 uid 或 dingId 查询部门配置 */
  async findByUid(dto: { userId?: string; dingId?: string }) {
    if (!(dto.userId || dto.dingId)) {
      throw new Error('userId 或 dingId 不能为空');
    }

    const member = await this.memberService.findOne({
      dingUserId: dto.dingId,
      userId: dto.userId,
    });

    if (!member) throw new Error('用户不存在');

    const deptId = member.deptIdList.split(',');

    return this.repository.findBy({ id: In(deptId) });
  }

  async update(dto: UpdateDepartmentConfigDto) {
    await this.repository.update(dto.id, dto);
  }

  // 每天凌晨3点
  @Cron('0 0 03 * * *')
  async sync() {
    const department = await this.departmentService.find({ active: 1 });

    if (!department.length) return;

    const all = await this.repository.find();

    for (const item of department) {
      const origin = all.find((v) => v.id === item.id);

      if (origin) {
        if (
          !(item.displayName === origin.name && item.active === origin.status)
        ) {
          await this.repository.update(origin.id, {
            name: item.displayName,
            status: item.active,
          });
        }
      } else {
        await this.repository.save(
          plainToInstance(DepartmentConfig, {
            id: item.id,
            name: item.displayName,
            status: 1,
          }),
        );
      }
    }
  }

  async switch(dto: SwitchDepartmentConfigDto) {
    await this.repository.update(dto.id, {
      addPointsNotice: dto.addPointsNotice,
      enableOvertimeAuth: dto.enableOvertimeAuth,
    });
  }
}
